package com.christina.engine.strategy;

import com.christina.engine.strategy.model.RoutingContext;
import com.christina.engine.strategy.model.RoutingDecision;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 路由策略管理器
 * 负责管理和执行路由策略
 * 
 * @author Christina
 */
@Slf4j
@Component
public class RoutingStrategyManager {
    
    private final Map<String, RoutingStrategy> strategies = new ConcurrentHashMap<>();
    private final List<RoutingStrategy> orderedStrategies = new ArrayList<>();
    private volatile boolean strategiesOrdered = false;
    
    /**
     * 注册路由策略
     * 
     * @param strategy 路由策略
     */
    public void registerStrategy(RoutingStrategy strategy) {
        if (strategy == null) {
            throw new IllegalArgumentException("Strategy cannot be null");
        }
        
        String strategyName = strategy.getStrategyName();
        if (strategyName == null || strategyName.trim().isEmpty()) {
            throw new IllegalArgumentException("Strategy name cannot be null or empty");
        }
        
        strategies.put(strategyName, strategy);
        strategiesOrdered = false;
        
        log.info("Registered routing strategy: {} with priority: {}", 
                strategyName, strategy.getPriority());
    }
    
    /**
     * 注销路由策略
     * 
     * @param strategyName 策略名称
     */
    public void unregisterStrategy(String strategyName) {
        RoutingStrategy removed = strategies.remove(strategyName);
        if (removed != null) {
            strategiesOrdered = false;
            log.info("Unregistered routing strategy: {}", strategyName);
        }
    }
    
    /**
     * 执行路由决策
     * 
     * @param context 路由上下文
     * @return 路由决策结果
     */
    public RoutingDecision makeRoutingDecision(RoutingContext context) {
        if (context == null) {
            return RoutingDecision.failure("Routing context is null", "RoutingStrategyManager");
        }
        
        ensureStrategiesOrdered();
        
        // 获取适用的策略
        List<RoutingStrategy> applicableStrategies = getApplicableStrategies(context);
        
        if (applicableStrategies.isEmpty()) {
            log.warn("No applicable routing strategies found for context: {}", context);
            return RoutingDecision.failure("No applicable routing strategies found", "RoutingStrategyManager");
        }
        
        // 尝试每个适用的策略
        RoutingDecision bestDecision = null;
        double bestScore = -1.0;
        
        for (RoutingStrategy strategy : applicableStrategies) {
            try {
                RoutingDecision decision = strategy.makeDecision(context);
                if (decision != null && decision.isSuccessful()) {
                    double score = calculateDecisionScore(decision, strategy, context);
                    
                    if (score > bestScore) {
                        bestScore = score;
                        bestDecision = decision;
                    }
                    
                    // 如果找到高置信度的决策，直接返回
                    if (decision.isHighConfidence()) {
                        log.debug("High confidence decision found by strategy: {}", strategy.getStrategyName());
                        return decision;
                    }
                }
            } catch (Exception e) {
                log.error("Error executing routing strategy: {}", strategy.getStrategyName(), e);
            }
        }
        
        if (bestDecision != null) {
            log.debug("Best routing decision selected with score: {}", bestScore);
            return bestDecision;
        }
        
        // 如果没有成功的决策，返回默认决策
        return createDefaultDecision(context);
    }
    
    /**
     * 获取适用的策略列表
     * 
     * @param context 路由上下文
     * @return 适用的策略列表
     */
    private List<RoutingStrategy> getApplicableStrategies(RoutingContext context) {
        return orderedStrategies.stream()
                .filter(strategy -> {
                    try {
                        return strategy.isApplicable(context);
                    } catch (Exception e) {
                        log.error("Error checking strategy applicability: {}", strategy.getStrategyName(), e);
                        return false;
                    }
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 计算决策得分
     * 
     * @param decision 路由决策
     * @param strategy 使用的策略
     * @param context 路由上下文
     * @return 决策得分
     */
    private double calculateDecisionScore(RoutingDecision decision, RoutingStrategy strategy, RoutingContext context) {
        double score = 0.0;
        
        // 基础置信度权重 (40%)
        if (decision.getConfidence() != null) {
            score += decision.getConfidence() * 0.4;
        }
        
        // 策略置信度权重 (30%)
        try {
            double strategyConfidence = strategy.getConfidence(context);
            score += strategyConfidence * 0.3;
        } catch (Exception e) {
            log.warn("Error getting strategy confidence: {}", strategy.getStrategyName(), e);
        }
        
        // 策略优先级权重 (20%)
        int maxPriority = orderedStrategies.stream()
                .mapToInt(RoutingStrategy::getPriority)
                .max()
                .orElse(1);
        if (maxPriority > 0) {
            score += (double) strategy.getPriority() / maxPriority * 0.2;
        }
        
        // 决策权重 (10%)
        if (decision.getWeight() != null) {
            score += decision.getWeight() * 0.1;
        }
        
        return Math.min(score, 1.0); // 确保得分不超过1.0
    }
    
    /**
     * 创建默认决策
     * 
     * @param context 路由上下文
     * @return 默认路由决策
     */
    private RoutingDecision createDefaultDecision(RoutingContext context) {
        // 根据意图类型创建默认路由
        if (context.getIntent() != null) {
            String intentType = context.getIntent().getType().name();
            String defaultService = getDefaultServiceForIntent(intentType);
            
            return RoutingDecision.builder()
                    .targetService(defaultService)
                    .confidence(0.3) // 低置信度
                    .reason("Default routing based on intent type: " + intentType)
                    .strategyName("DefaultStrategy")
                    .valid(true)
                    .needsFallback(true)
                    .fallbackService("ChatDomainService") // 默认回退到聊天服务
                    .build();
        }
        
        // 如果没有意图信息，默认路由到聊天服务
        return RoutingDecision.builder()
                .targetService("ChatDomainService")
                .confidence(0.2) // 很低置信度
                .reason("Default routing - no intent information available")
                .strategyName("DefaultStrategy")
                .valid(true)
                .needsFallback(false)
                .build();
    }
    
    /**
     * 根据意图类型获取默认服务
     * 
     * @param intentType 意图类型
     * @return 默认服务名称
     */
    private String getDefaultServiceForIntent(String intentType) {
        switch (intentType.toLowerCase()) {
            case "travel":
            case "travel_planning":
            case "booking":
                return "TravelDomainService";
            case "chat":
            case "question":
            case "general":
                return "ChatDomainService";
            case "user":
            case "profile":
            case "settings":
                return "UserDomainService";
            default:
                return "ChatDomainService";
        }
    }
    
    /**
     * 确保策略按优先级排序
     */
    private void ensureStrategiesOrdered() {
        if (!strategiesOrdered) {
            synchronized (this) {
                if (!strategiesOrdered) {
                    orderedStrategies.clear();
                    orderedStrategies.addAll(strategies.values());
                    orderedStrategies.sort((s1, s2) -> Integer.compare(s2.getPriority(), s1.getPriority()));
                    strategiesOrdered = true;
                }
            }
        }
    }
    
    /**
     * 获取所有注册的策略
     * 
     * @return 策略映射
     */
    public Map<String, RoutingStrategy> getAllStrategies() {
        return new HashMap<>(strategies);
    }
    
    /**
     * 获取策略数量
     * 
     * @return 策略数量
     */
    public int getStrategyCount() {
        return strategies.size();
    }
    
    /**
     * 检查是否有指定名称的策略
     * 
     * @param strategyName 策略名称
     * @return 是否存在
     */
    public boolean hasStrategy(String strategyName) {
        return strategies.containsKey(strategyName);
    }
    
    /**
     * 获取指定名称的策略
     * 
     * @param strategyName 策略名称
     * @return 策略实例，如果不存在返回null
     */
    public RoutingStrategy getStrategy(String strategyName) {
        return strategies.get(strategyName);
    }
    
    /**
     * 清空所有策略
     */
    public void clearStrategies() {
        strategies.clear();
        orderedStrategies.clear();
        strategiesOrdered = false;
        log.info("All routing strategies cleared");
    }
    
    /**
     * 获取管理器统计信息
     * 
     * @return 统计信息
     */
    public Map<String, Object> getStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalStrategies", strategies.size());
        stats.put("strategyNames", new ArrayList<>(strategies.keySet()));
        
        Map<String, Integer> priorityDistribution = strategies.values().stream()
                .collect(Collectors.groupingBy(
                        s -> "Priority_" + s.getPriority(),
                        Collectors.collectingAndThen(Collectors.counting(), Math::toIntExact)
                ));
        stats.put("priorityDistribution", priorityDistribution);
        
        return stats;
    }
}